#include <usb/usb_ddk_api.h>
#define LOG_TAG "testTag [NATIVE]"

#include "inject_thread.h"
#include "data_parser.h"

#include <hilog/log.h>
std::mutex InjectThread::mutex_;
std::condition_variable InjectThread::conditionVariable_;
std::vector<EmitItem> InjectThread::injectList_;

extern "C" {
extern int32_t OH_Usb_CreateDevice(uint32_t maxX, uint32_t maxY, uint32_t maxPressure);
extern int32_t OH_Usb_EmitEvent(int32_t deviceId, const EmitItem items[], uint32_t length);
extern int32_t OH_Usb_DestroyDevice(int32_t deviceId);
}

InjectThread::InjectThread() {
    isRunning_ = true;
}

InjectThread::~InjectThread() {
    isRunning_ = false;
    conditionVariable_.notify_one();
}

void InjectThread::RunThread(void *param) {
    InjectThread *thread = (InjectThread *)param;
    thread->InjectFunc();
}

void InjectThread::Start() {
    thread_ = std::thread(InjectThread::RunThread, this);
    pthread_setname_np(thread_.native_handle(), "emitEvent");
    thread_.detach();
}

void InjectThread::InjectFunc() const {
    std::unique_lock<std::mutex> uniqueLock(mutex_);

    uint32_t maxX, maxY, maxPressure;
    DataParser::GetInstance().GetAbsMax(maxX, maxY, maxPressure);
    OH_LOG_INFO(LOG_APP, "OH_Usb_CreateDevice maxX:%{public}d, maxY:%{public}d, maxPressure:%{public}d",
                maxX, maxY, maxPressure);
    int deviceId = OH_Usb_CreateDevice(maxX, maxY, maxPressure);
    while (isRunning_) {
        conditionVariable_.wait(uniqueLock);
        //OH_LOG_INFO(LOG_APP, "OH_Usb_EmitEvent size:%{public}lu deviceId:%{public}d", injectList_.size(), deviceId_);
        for (auto &item : injectList_) {
            //OH_LOG_INFO(LOG_APP, "OH_Usb_EmitEvent type:%{public}d code:%{public}d value:%{public}d", item.type, item.code, item.value);
        }
        OH_Usb_EmitEvent(deviceId_, injectList_.data(), (uint32_t)injectList_.size());
        injectList_.clear();
    }
    OH_LOG_INFO(LOG_APP, "OH_Usb_DestroyDevice deviceId:%{public}d", deviceId);
    OH_Usb_DestroyDevice(deviceId);
}

void InjectThread::InjectEvent(EmitItem &injectInputEvent) const {
    std::lock_guard<std::mutex> lockGuard(mutex_);
    injectList_.push_back(injectInputEvent);
}

void InjectThread::Sync() {
    if (injectList_.size() > 0) {
        conditionVariable_.notify_one();
    }
}